import { h, ref, onMounted, onUnmounted, watch } from 'vue'
import { ElSkeleton } from 'element-plus'

// 或者使用 getCurrentInstance 不用div包裹
export default function createLazyLoadComp({ comp, store }) {
  return {
    props: comp.props,
    setup(props, context) {
      // DOM节点用于挂载监控元素
      const elRef = ref(null)
      // 是否进入可视区域
      const enterVision = ref(false)
      // 图表数据是否准备好
      const dataReady = ref(false)

      const callback = (entries, observer) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            enterVision.value = true
            observer.disconnect()
          }
        })
      }
      const options = {
        root: null,
        rootMargin: '0px',
        threshold: 0.1
      }
      // 实例化观察者
      const intersectionObserver = new IntersectionObserver(callback, options)
      // 监听是否进入可视区域
      const unwatch = watch(
        () => enterVision.value,
        async newValue => {
          if (newValue) {
            try {
              // 请求数据 为第一次渲染图表做准备
              await store.getDate({ url: 'api/echart1' })

              // 判断获取信息是否成功
              if (store.view.status === 2) {
                // 修改数据准备状态 用于取消骨架屏
                dataReady.value = true
              }
            } catch (error) {
              // 错误处理
              dataReady.value = false
            }
          }
        },
        { immediate: true }
      )
      // 组件挂载时才会获取元素避免出现错误
      onMounted(() => {
        if (elRef.value) {
          intersectionObserver.observe(elRef.value)
        }
      })
      // 组件销毁时处理 watch 和 intersectionObserver
      onUnmounted(() => {
        unwatch()
        intersectionObserver.disconnect()
      })

      return () => {
        // 为图表组件传递 store 便于图表组件轮询数据
        return h('div', { ref: elRef }, [dataReady.value === false || enterVision.value === false ? h(ElSkeleton, { animated: true }) : h(comp, { ...context.attrs, store: store })])
      }
    }
  }
}
